package Unite;

import java.awt.Point;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;

import Game.TableValeurs;

public class Legion {
	private static int ID_LEGION = 0;
	private Map<Integer, Vector<Unit>> _allUnits;
	private Vector<Unit> _unitsToRemove;
	private int _id;
	private double _weight;

	private Point _pos;

	/**
	 * @param allUnits
	 */
	public Legion(Vector<Unit> allUnits) {
		_pos = new Point();
		_id = ID_LEGION;
		++ID_LEGION;
		_unitsToRemove = new Vector<Unit>();
		_allUnits = new HashMap<Integer, Vector<Unit>>();

		if (allUnits != null)
			for (Unit units : allUnits)
				add(units);
	}

	/**
	 * 
	 */
	public Legion() {
		_pos = new Point();
		_id = ID_LEGION;
		++ID_LEGION;

		_allUnits = new HashMap<Integer, Vector<Unit>>();
		_weight = 0;
		_unitsToRemove = new Vector<Unit>();
	}

	/**
	 * @param unit
	 * @return
	 */
	public boolean add(Unit unit) {

		if (_allUnits.get(unit.getClasseId()) == null) {
			_allUnits.put(unit.getClasseId(), new Vector<Unit>());
		}
		_allUnits.get(unit.getClasseId()).add(unit);
		_weight += unit.getWeight();
		return false;
	}

	// présentement, la nouvelle légion qui est issue du split est à la même
	// position que son parent... elles sont donc superposées.
	public Legion splitLegion() {
		Legion newLegion = new Legion();
		newLegion.setPos(_pos.x, _pos.y);
		for (Map.Entry<Integer, Vector<Unit>> entry : _allUnits.entrySet()) {
			for (int i = (int) ((entry.getValue()).size() / 2); i < entry
					.getValue().size(); ++i) {
				_unitsToRemove.add(entry.getValue().elementAt(i));
				newLegion.add(entry.getValue().elementAt(i));
			}
		}
		removeUnits();
		return newLegion;
	}

	/**
	 * @param allUnit
	 * @return
	 * 
	 *         cette méthode n'est plus utilisée depuis que les Units du vecteur
	 *         de Unit que reçoit le constructeur de Légion sont ajoutées une à
	 *         une.
	 */
	@SuppressWarnings("unused")
	private int calculateWeight(Vector<Unit> allUnits) {
		int weight = 0;
		for (Unit u : allUnits) {
			weight += u.getWeight();
		}

		return weight;
	}

	/**
	 * @return un vecteur d'unite
	 */
	public Vector<Unit> getUnits() {
		Vector<Unit> units = new Vector<Unit>();
		for (Map.Entry<Integer, Vector<Unit>> entry : _allUnits.entrySet())
			units.addAll(entry.getValue());

		return units;
	}

	/**
	 * @return id de la legion
	 */
	public int getId() {
		return _id;
	}

	/**
	 * @return le poids d'une legion
	 */
	public double getWeight() {
		return _weight;
	}

	/**
	 * @return le map de toutes les unites
	 */
	public Map<Integer, Vector<Unit>> getAllUnitsMap() {
		return _allUnits;
	}

	/**
	 * @return le nombre d'unite
	 */
	public int getNbUnits() {
		int nbUnits = 0;
		for (Map.Entry<Integer, Vector<Unit>> entry : _allUnits.entrySet())
			nbUnits += entry.getValue().size();

		return nbUnits;
	}

	/**
	 * @param x
	 * @param y
	 */
	public void setPos(int x, int y) {
		_pos.x = x;
		_pos.y = y;
	}

	/**
	 * @return la position
	 */
	public Point getPos() {
		return _pos;
	}

	/**
	 * @return position en x
	 */
	public int getX() {
		return _pos.x;
	}

	/**
	 * @return position en y
	 */
	public int getY() {
		return _pos.y;
	}

	/**
	 * @param u
	 */
	public void remove(Unit u) {// private void setAllUnits(Vector<Unit>
								// allUnits) {
		// for (Unit u : allUnits) {
		// add(u);
		// }
		_weight -= u.getWeight();
		_allUnits.get(u.getClasseId()).remove(u);
	}

	/**
	 * @param unitCurrent
	 */
	public void setToRemove(Unit unitCurrent) {
		System.out.println("Unit to remove: " + unitCurrent.getId());
		_unitsToRemove.add(unitCurrent);
	}

	/**
	 * @return
	 */
	public int removeUnits() {
		int unitsRemoved = 0;
		for (Unit u : _unitsToRemove) {
			remove(u);
			unitsRemoved++;
		}
		_unitsToRemove.clear();
		return unitsRemoved;
	}

	/**
	 * @param allUnits
	 */
	@SuppressWarnings("unused")
	private void setAllUnits(Vector<Unit> allUnits) {
		for (Unit u : allUnits) {
			add(u);
		}
	}

	/**
	 * La vitesse a laquelle se deplace l'unite la plus lente. Determine la
	 * vitesse de la legion
	 * 
	 * @param tv
	 * @param terrainId
	 * @return
	 */
	public double getSpeed(TableValeurs tv, int terrainId) {
		double low = 100.0;
		for (Map.Entry<Integer, Vector<Unit>> entry : _allUnits.entrySet()) {
			double res = tv.getDeplacement(entry.getKey(), terrainId);
			if (res < low)
				low = res;
		}
		return low;
	}

	public boolean equalsPos(Point p) {
		return _pos.equals(p);
	}

	/**
	 * @return
	 */
	public String getInfos() {
		String a;
		a = getWeight() + " " + getX() + " " + getY() + " ";
		if (_allUnits.get(Unit.GUERRIER) != null)
			a += _allUnits.get(Unit.GUERRIER).size();
		else
			a+="0";
		a+=" ";
		if (_allUnits.get(Unit.ARCHER) != null)
			a += _allUnits.get(Unit.ARCHER).size();
		else
			a+="0";
		a+=" ";
		if (_allUnits.get(Unit.CHEVALIER) != null)
			a += _allUnits.get(Unit.CHEVALIER).size();
		else
			a+="0";
		a+=" ";
		if (_allUnits.get(Unit.TORUK) != null)
			a += _allUnits.get(Unit.TORUK).size();
		else
			a+="0";
		a+=" ";

		return a;
	}

}
